package com.admin4j.server.system.manager.impl;

import com.admin4j.server.system.convert.SysUserConvert;
import com.admin4j.server.system.entity.SysUser;
import com.admin4j.server.system.entity.vo.MenuVO;
import com.admin4j.server.system.entity.vo.SysUserLoginInfoVO;
import com.admin4j.server.system.manager.IUserProfileService;
import com.admin4j.server.system.mapper.SysRoleMapper;
import com.admin4j.server.system.mapper.SysUserMapper;
import com.admin4j.server.system.service.ISysMenuService;
import com.admin4j.server.system.service.ISysPermissionService;
import com.admin4j.server.system.service.ISysUserService;
import com.alicp.jetcache.Cache;
import com.alicp.jetcache.CacheManager;
import com.alicp.jetcache.anno.CacheType;
import com.alicp.jetcache.template.QuickConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.time.Duration;
import java.util.List;

/**
 * @author andanyang
 * @since 2023/11/14 14:21
 */
@Service
public class UserProfileServiceImpl implements IUserProfileService {

    @Autowired
    ISysMenuService sysMenuService;
    @Autowired
    ISysUserService sysUserService;
    @Autowired
    ISysPermissionService sysPermissionService;

    @Autowired
    SysUserMapper sysUserMapper;
    @Autowired
    SysRoleMapper sysRoleMapper;

    @Autowired
    CacheManager cacheManager;

    Cache<Long, SysUserLoginInfoVO> sysUserLoginInfoVOCache;

    @PostConstruct
    public void init() {
        QuickConfig qc = QuickConfig.newBuilder("SysUser:")
                .expire(Duration.ofHours(24))
                .cacheType(CacheType.BOTH) // two level cache
                .syncLocal(true) // invalidate local cache in all jvm process after update
                .build();
        sysUserLoginInfoVOCache = cacheManager.getOrCreateCache(qc);
    }

    /**
     * 我的菜单
     * TODO CACHE
     *
     * @return
     */
    public List<MenuVO> menus(Long userId) {
        return sysMenuService.treeByUserId(userId);
    }

    //---------------------------------------------------------------- userInfo ----------------------------------------------------------------

    /**
     * 根据用户ID获取用户登录信息
     *
     * @param userId
     * @return
     */
    @Override
    public SysUserLoginInfoVO getUserInfoByUserId(Long userId) {
        return sysUserLoginInfoVOCache.computeIfAbsent(userId, (key) -> getByUserIdFormDB(userId));
    }


    /**
     * 根据用户ID从数据库里查询用户登录信息
     *
     * @param userId
     * @return
     */
    public SysUserLoginInfoVO getByUserIdFormDB(Long userId) {

        SysUser sysUser = sysUserMapper.getByUserId(userId);
        if (sysUser == null) {
            return null;
        }

        SysUserLoginInfoVO userInfo = SysUserConvert.INSTANCE.convert(sysUser);
        // 是否是管理员
        userInfo.setAdmin(sysRoleMapper.isAdmin(userId) != null);
        List<String> permissionCodes = permissionCodes(userId);
        // 权限code
        userInfo.setPermissions(permissionCodes);
        return userInfo;
    }

    /**
     * 清理用户缓存
     *
     * @param userId
     */
    @Override
    public void clearUserCache(Long userId) {
        sysUserLoginInfoVOCache.remove(userId);
        sysPermissionService.clearCache(userId);
    }

    //---------------------------------------------------------------- permission ----------------------------------------------------------------
    // 用户权限字符串
    @Override
    public List<String> permissionCodes(Long userId) {
        return sysPermissionService.permissionCodes(userId);
    }
}
